const Ajv = require('ajv');
const _ = require('lodash');
const formSchemas = require('./form-schemas');
const Config = require('./config.js');
const { getLogger } = require('./logging.js');

const logger = getLogger(Config.LOG_LEVEL);

const schemaFormMap = {
  'SAS1012': formSchemas.SAS1012,
  'SAS1013': formSchemas.SAS1013,
  'SAS1014': formSchemas.SAS1014,
  'SAS1017': formSchemas.SAS1017,
  'SAS1018': formSchemas.SAS1018,
  'SAS1022': formSchemas.SAS1022,
  'SAS1023': formSchemas.SAS1023,
  'SAS1025': formSchemas.SAS1025,
  'SAS1026': formSchemas.SAS1026
};

const defsSchema = {
  '$id': 'defsSchema.json',
  'type': 'object',
  'definitions': {
    'typeOfAppointment': {
      'type': 'object',
      'properties': {
        'apptType': {
          'type': 'string'
        },
        'pendingBiz': {
          'type': 'boolean',
          'enum': [true, false],
          'default': false
        }
      }
    },
    'entityInformation': {
      'type': 'object',
      'description':
        'Information about the agency entity, used on forms SAS1014, SAS1022',
      'required': [
        'agencyLicName',
        'agencyTaxID',
        'agencyPhone',
        'businessMailingAddress'
      ],
      'properties': {
        'agencyLicName': {
          'type': 'string',
          'description': 'Licensed entity name'
        },
        'agencyTaxID': {
          'type': 'string',
          'description': 'Federal Tax ID Number'
        },
        'agencyDBA': {
          'type': 'string',
          'description': 'DBA'
        },
        'agencyStateAppts': {
          'type': 'string',
          'description': 'States business will be written in'
        },
        'agencyTotalAgents': {
          'type': 'string',
          'description': 'Total number of reps/agents'
        },
        'businessMailingAddress': {
          '$ref': '#/definitions/busMailAddress'
        },
        'businessLocationAddress': {
          '$ref': '#/definitions/busLocAddress'
        },
        'agencyWebsite': {
          'type': 'string',
          'description': 'Website'
        },
        'agencyPhone': {
          'type': 'string',
          'description': 'Phone number'
        },
        'agencyFax': {
          'type': 'string',
          'description': 'Fax'
        }
      }
    },
    'applicantInformation': {
      'type': 'object',
      'description':
        'Information about the applicant, used on forms SAS1012, SAS1013, SAS1018, SAS1017,SAS1025',
      'properties': {
        'applicantFirstName': {
          'type': 'string',
          'description': 'Licensed Name First'
        },
        'applicantLastName': {
          'type': 'string',
          'description': 'Licensed Name Last'
        },
        'applicantMiddleName': {
          'type': 'string',
          'description': 'Licensed Name M.I.'
        },
        'applicantSSN': {
          'type': 'string',
          'description': 'SSN ID #'
        },
        'applicantDOB': {
          'type': 'string',
          'description': 'Date of birth'
        },
        'applicantGender': {
          'type': 'string',
          'description': 'Gender'
        },
        'residentMailingAddress': {
          '$ref': '#/definitions/residentAddress'
        },
        'businessMailingAddress': {
          '$ref': '#/definitions/busMailAddress'
        },
        'businessLocationAddress': {
          '$ref': '#/definitions/busLocAddress'
        },
        'applicantEmail': {
          'type': 'string',
          'description': 'Email address'
        },
        'applicantBizPhone': {
          'type': 'string',
          'description': 'Phone number (Business)'
        },
        'applicantCell': {
          'type': 'string',
          'description': 'Phone number (Cell)'
        },
        'applicantFax': {
          'type': 'string',
          'description': 'Phone number (Fax)'
        }
      },
      'anyOf': [
        {
          'required': [
            'applicantFirstName',
            'applicantLastName',
            'applicantSSN',
            'applicantDOB',
            'residentMailingAddress',
            'businessMailingAddress',
            'applicantEmail'
          ]
        },
        {
          'required': [
            'applicantFirstName',
            'applicantLastName',
            'applicantSSN',
            'applicantDOB',
            'residentMailingAddress',
            'businessMailingAddress',
            'applicantBizPhone'
          ]
        }
      ]
    },
    'entityLicensesRegistration': {
      'type': 'object',
      'description':
        'Information about the entity Licenses and Registration, used on forms SAS1012, SAS1014, SAS1022',
      'properties': {
        'residentLicState': {
          'type': 'string',
          'description': 'Resident license state'
        },
        'licenseNumber': {
          'type': 'string',
          'description': 'License number'
        },
        'nrApptStates': {
          'type': 'string',
          'description': 'Non-resident Appointments (list states needed)'
        },
        'crdNum': {
          'type': 'string',
          'description': 'CRD Number'
        }
      }
    },
    'principalAuthorizedCompSigner': {
      'type': 'object',
      'description':
        'Information about the Principal/Owner or Authorized Company Signer, used on forms SAS1014, SAS1022',
      'properties': {
        'agencyAuthName': {
          'type': 'string',
          'description': 'Name'
        },
        'agencyAuthTitle': {
          'type': 'string',
          'description': 'Title'
        },
        'agencyAuthSSN': {
          'type': 'string',
          'description': 'SSN'
        },
        'agencyAuthDOB': {
          'type': 'string',
          'description': 'Date of birth'
        },
        'agencyAuthEmail': {
          'type': 'string',
          'description': 'Email address'
        },
        'agencyAuthAppt': {
          'type': 'boolean',
          'description': 'Does Principal/Owner need to be appointed to sell?',
          'enum': [true, false]
        },
        'agencyAuthBizPhone': {
          'type': 'string',
          'description': 'Phone number (Business)'
        },
        'agencyAuthCell': {
          'type': 'string',
          'description': 'Phone number (Cell)'
        },
        'agencyAuthFax': {
          'type': 'string',
          'description': 'Phone number (Fax)'
        }
      },
      'anyOf': [
        {
          'required': [
            'agencyAuthName',
            'agencyAuthSSN',
            'agencyAuthDOB',
            'agencyAuthEmail'
          ]
        },
        {
          'required': [
            'agencyAuthName',
            'agencyAuthSSN',
            'agencyAuthDOB',
            'agencyAuthBizPhone'
          ]
        }
      ]
    },
    'commissionPayment': {
      'type': 'object',
      'description':
        'Information about the Commission Payment, used on forms SAS1013, SAS1014, SAS1022, SAS1025',
      'required': [
        'commPayMethod',
        'commPayFreq',
        'commBankAcctType',
        'commBankAcctName',
        'commBankInstName',
        'commBankAcctNum',
        'commBankRoutingNum'
      ],
      'properties': {
        'commPayMethod': {
          'type': 'string',
          'enum': ['EFT'],
          'description': 'Commmission payment method'
        },
        'commPayFreq': {
          'type': 'string',
          'enum': ['Weekly', 'Monthly', 'Bi-weekly', 'Quarterly'],
          'description': 'Payment frequency'
        },
        'commBankAcctType': {
          'type': 'string',
          'enum': ['Checking', 'Savings'],
          'description': 'Bank account type'
        },
        'commBankAcctName': {
          'type': 'string',
          'description': 'Bank account name'
        },
        'commBankAcctNum': {
          'type': 'string',
          'description': 'Bank account Number'
        },
        'commBankRoutingNum': {
          'type': 'string',
          'description': 'Bank routing number'
        },
        'commBankInstName': {
          'type': 'string',
          'description': 'Bank institution name'
        }
      }
    },
    'backgroundInformation': {
      'type': 'object',
      'description': 'Background Information questionnaire',
      'required': [
        'bgInfoOne',
        'bgInfoTwo',
        'bgInfoThree',
        'bgInfoFour',
        'bgInfoFive',
        'bgInfoSix',
        'bgInfoSeven',
        'bgInfoEight',
        'bgInfoNine',
        'bgInfoTen',
        'bgInfoEleven',
        'bgInfoTwelve'
      ],
      'properties': {
        'bgInfoOne': {
          'type': 'boolean',
          'description':
            'Has an errors and omissions claim been filed against you?',
          'enum': [true, false]
        },
        'bgInfoTwo': {
          'type': 'boolean',
          'description':
            'Has any life insurance company cancelled your contract/appointment or forced you to resign for any reason other than production?',
          'enum': [true, false]
        },
        'bgInfoThree': {
          'type': 'boolean',
          'description':
            'Have you ever been charged, indicted, arrested, or convicted of any crime, regardless of the nature, outcome or disposition?',
          'enum': [true, false]
        },
        'bgInfoFour': {
          'type': 'boolean',
          'description':
            'Has your insurance license or securities registration ever been suspended or revoked?',
          'enum': [true, false]
        },
        'bgInfoFive': {
          'type': 'boolean',
          'description':
            'Have you ever been named in any inquiry or complaint by any regulator (including the SEC or FINRA)?',
          'enum': [true, false]
        },
        'bgInfoSix': {
          'type': 'boolean',
          'description':
            'Within the past 10 years have you filed for bankruptcy?',
          'enum': [true, false]
        },
        'bgInfoSeven': {
          'type': 'boolean',
          'description':
            'Within the past 10 years have you exercised control over an organization that filed for bankruptcy based on events that occurred while under your control?',
          'enum': [true, false]
        },
        'bgInfoEight': {
          'type': 'boolean',
          'description':
            'Are you currently subject to a lien by the IRS or any other entity?',
          'enum': [true, false]
        },
        'bgInfoNine': {
          'type': 'boolean',
          'description':
            'Are you now or have you ever been involved in insurance or any investment-related litigation, arbitration or similar matter?',
          'enum': [true, false]
        },
        'bgInfoTen': {
          'type': 'boolean',
          'description':
            'Are there currently any outstanding or unsatisfied judgments or liens against you?',
          'enum': [true, false]
        },
        'bgInfoEleven': {
          'type': 'boolean',
          'description':
            'Do you currently owe or have an outstanding obligation or debt to any entity, employer, or insurer related to your insurance or investment business?',
          'enum': [true, false]
        },
        'bgInfoTwelve': {
          'type': 'boolean',
          'description':
            'Are you currently involved in any pending or unresolved customer complaint?',
          'enum': [true, false]
        }
      }
    },
    'errorsOmissions': {
      'type': 'object',
      'description':
        'Errors & Omissions Insurance is required for appointment, used on forms SAS1013, SAS1014, SAS1022, SAS1025',
      'required': [
        'agencyEnoCoverage',
        'agencyEnoAppSign',
        'agencyEnoAppSignDate'
      ],
      'properties': {
        'agencyEnoCoverage': {
          'type': 'boolean',
          'enum': [true, false],
          'description': 'Do you carry current Errors & Omissions Coverage?'
        },
        'agencyEnoAppSign': {
          'type': 'string',
          'description': 'Applicant Signature'
        },
        'agencyEnoAppSignDate': {
          'type': 'string',
          'description': 'Date'
        }
      }
    },
    'fairCreditReporting': {
      'type': 'object',
      'description':
        'Fair Credit Reporting Act Disclosure and Authorization to Obtain Consumer Reports',
      'required': ['appSignature', 'appSignDate'],
      'properties': {
        'appSignature': {
          'type': 'boolean',
          'enum': [true, false],
          'description': 'Applicant Signature'
        },
        'appSignDate': {
          'type': 'string',
          'description': 'Application Sign Date'
        },
        'OKMNBGReport': {
          'type': 'boolean',
          'description':
            'Oklahoma and Minnesota agents only: Check here if you would like a copy of your background investigation report.',
          'enum': [true, false]
        }
      }
    },
    'residentAddress': {
      'type': 'object',
      'properties': {
        'residentAddress': {
          'type': 'string',
          'Description': 'Resident street address'
        },
        'residentCity': {
          'type': 'string',
          'Description': 'Resident City'
        },
        'residentState': {
          'type': 'string',
          'Description': 'Resident State'
        },
        'residentZip': {
          'type': 'string',
          'Description': 'Resident Zip'
        }
      },
      'required': [
        'residentAddress',
        'residentCity',
        'residentState',
        'residentZip'
      ]
    },
    'busMailAddress': {
      'type': 'object',
      'properties': {
        'businessMailAddress': {
          'type': 'string',
          'Description': 'Business mailing address'
        },
        'businessMailCity': {
          'type': 'string',
          'Description': 'Business City'
        },
        'businessMailState': {
          'type': 'string',
          'Description': 'Business State'
        },
        'businessMailZip': {
          'type': 'string',
          'Description': 'Business Zip'
        }
      },
      'required': [
        'businessMailAddress',
        'businessMailCity',
        'businessMailState',
        'businessMailZip'
      ]
    },
    'busLocAddress': {
      'type': 'object',
      'properties': {
        'businessLocAddress': {
          'type': 'string',
          'Description': 'Business location address'
        },
        'businessLocCity': {
          'type': 'string',
          'Description': 'Business location City'
        },
        'businessLocState': {
          'type': 'string',
          'Description': 'Business location State'
        },
        'businessLocZip': {
          'type': 'string',
          'Description': 'Business location Zip'
        }
      }
    }
  }
};

class FormSchemaValidator {
  constructor (forms) {
    this.forms = forms;
    this.errors = undefined;
  }

  async check () {
    const errors = {};
    const validateFormSchema = this.validateFormSchema;

    this.forms.forEach(function (form) {
      const validationErrors = validateFormSchema(form);
      if (validationErrors.length > 0) {
        logger.info(`Errors were found validating ${form.formNumber}.  Errors:  ${JSON.stringify(validationErrors)}`);
        errors[form.formNumber] = validationErrors;
      }
    });
    this.errors = errors;

    if (_.isEmpty(errors)) {
      return true;
    } else {
      return false;
    }
  }

  validateFormSchema (form) {
    const ajv = new Ajv({ 'strictTypes': false, 'strict': false, 'allErrors': true });

    const validateInput = ajv.addSchema(defsSchema).compile(schemaFormMap[form.formNumber]);
    const valid = validateInput(form);

    if (!valid) {
      return validateInput.errors;
    }
    return [];
  }
}

exports.FormSchemaValidator = FormSchemaValidator;
